package com.alibaba.idst.nls.demo;

import android.content.res.AssetManager;
import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.EditText;
import android.widget.RadioGroup;
import android.widget.TextView;
import android.widget.Toast;

import com.alibaba.idst.util.NlsClient;
import com.alibaba.idst.util.SpeechSynthesizer;
import com.alibaba.idst.util.SpeechSynthesizerCallback;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

/**
 * 语音合成
 */
public class SpeechSynthesizerActivity2 extends AppCompatActivity {
    private static final String TAG = "AliSpeechDemo";

    NlsClient client;
    private SpeechSynthesizer speechSynthesizer;//语音合成的桥梁，将文字上传到服务器进行语音的合成
    private RadioGroup mRgRate;//设置人声
    private RadioGroup mRgXb;//设置性别
    private EditText mEtSpeed;//设置语速
    private FileOutputStream mFos;//输出流
    private BufferedReader mBrContent;//内容
    private BufferedReader mBrName;//名字
    private String mCurrentName;//保存当前的文件的名字
    private TextView mTvResult;//设置数量
    private TextView mTvTime;//时间
    private int mTotalCount;//数量
    private long mStartTime;//开始时间
    private long mEndTime;//结束时间


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_speech_synthesizer2);

        initView();

        initBufferedReader();

        //创建client实例，client只需要创建一次，可以用它多次创建synthesizer
        client = new NlsClient();
    }

    private void initBufferedReader() {
        try {
            AssetManager manager = getResources().getAssets();
            InputStream isContent = manager.open("content.txt");
            mBrContent = new BufferedReader(new InputStreamReader(isContent));
        } catch (Exception e) {

        }

        try {
            AssetManager manager = getResources().getAssets();
            InputStream isName = manager.open("name.txt");
            mBrName = new BufferedReader(new InputStreamReader(isName));
        } catch (Exception e) {

        }

    }

    private void initView() {
        mTvResult = findViewById(R.id.tv_result);
        mTvTime = findViewById(R.id.tv_time);
        mRgRate = findViewById(R.id.rg_rate);
        mRgXb = findViewById(R.id.fg_xb);
        mEtSpeed = findViewById(R.id.et_speed);
        findViewById(R.id.btn_synth).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mStartTime = System.currentTimeMillis();
                startSynthesizer();
            }
        });
    }

    /**
     * 开始语音合成
     */
    public void startSynthesizer() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    //1、然后开始读取文件中的数据
                    String content = mBrContent.readLine();
                    String name = mBrName.readLine();
                    mCurrentName = name;
                    if (TextUtils.isEmpty(mCurrentName)){
                        Log.e(TAG,"结束了");
                        return;
                    }

                    //2、设置语音合成的参数
                    //设置语音合成的回调
                    SpeechSynthesizerCallback callback = new MyCallback();//语音合成的结果回调
                    speechSynthesizer = client.createSynthesizerRequest(callback);
                    //设置token和appkey
                    //请使用https://help.aliyun.com/document_detail/72153.html 动态生成token
                    speechSynthesizer.setToken("515adac435104bc28a0deef4fc2ec394");
                    //请使用阿里云语音服务管控台(https://nls-portal.console.aliyun.com/)生成您的appkey
                    speechSynthesizer.setAppkey("ZsrijlIWDi1ZWaVp");
                    //设置相关参数，以下选项都会改变最终合成的语音效果，可以按文档调整试听效果
                    //设置语音编码，pcm编码可以直接用audioTrack播放，其他编码不行
                    speechSynthesizer.setFormat(SpeechSynthesizer.FORMAT_PCM);
                    // 设置语音数据采样率
                    int rateId = mRgRate.getCheckedRadioButtonId();
                    if (rateId == R.id.rb_16) {
                        speechSynthesizer.setSampleRate(SpeechSynthesizer.SAMPLE_RATE_16K);
                    } else {
                        speechSynthesizer.setSampleRate(SpeechSynthesizer.SAMPLE_RATE_8K);
                    }
                    // 设置人声
                    int xbId = mRgXb.getCheckedRadioButtonId();
                    if (xbId == R.id.rb_female) {
                        speechSynthesizer.setVoice(SpeechSynthesizer.VOICE_XIAOYUN);
                    } else {
                        speechSynthesizer.setVoice(SpeechSynthesizer.VOICE_XIAOGANG);
                    }
                    // 设置语音合成方法
                    speechSynthesizer.setMethod(SpeechSynthesizer.METHOD_RUS);
                    // 设置语速,默认为100
                    speechSynthesizer.setSpeechRate(Integer.parseInt(mEtSpeed.getText().toString()));
                    // 设置要转为语音的文本
                    speechSynthesizer.setText(content);
                    //创建合成的文件
                    createPcmFile(name);

                    //2、开始合成
                    int result = speechSynthesizer.start();

                    //3、对结果判断
                    if (result < 0) {
                        Toast.makeText(SpeechSynthesizerActivity2.this, "启动语音合成失败！", Toast.LENGTH_LONG).show();
                        speechSynthesizer.stop();
                        return;
                    }

                    //4、合成结束
                    Log.d(TAG, "speechSynthesizer start done");
                    speechSynthesizer.stop();
                } catch (Exception e) {

                }
            }
        }).start();
    }

    /**
     * 创建PCM文件
     */
    private void createPcmFile(String name) {
        Log.e(TAG, "创建要写入的pcm文件");
        //1、创建要写入的PCM文件
        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hdl_audio_cache/" + name +".pcm";
        try {
            File file = new File(path);
            if (!file.exists()) {
                file.createNewFile();
            }
            //2、封装流
            mFos = new FileOutputStream(file);
            Log.e(TAG, "创建输出流成功");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 文字转语音的回调
     */
    private class MyCallback implements SpeechSynthesizerCallback {

        // 语音合成开始的回调
        @Override
        public void onSynthesisStarted(String msg, int code) {
            Log.d(TAG, "识别开始");
        }

        /**
         * 获取音频数据
         *
         * @param data 音频数据
         * @param code
         */
        @Override
        public void onBinaryReceived(byte[] data, int code) {
            Log.e(TAG, "识别中：" + data.length);
            //将合成的数据写入文件中
            saveDataToFile(data);

        }

        // 语音合成完成的回调，在这里关闭播放器
        @Override
        public void onSynthesisCompleted(final String msg, int code) {
            setTvResult();
            //流刷新和关闭
            flushAndClose();
            //PCM转换为WAV
            convertPcm2Wav();
            //然后开始下一次合成
            startSynthesizer();
        }

        // 调用失败的回调
        @Override
        public void onTaskFailed(String msg, int code) {

        }

        // 连接关闭的回调
        @Override
        public void onChannelClosed(String msg, int code) {
        }
    }

    private void setTvResult() {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                //设置数量
                mTotalCount ++;
                mTvResult.setText("合成数量：" + mTotalCount);
                //设置总的时间
                mEndTime = System.currentTimeMillis();
                mTvTime.setText((mEndTime - mStartTime) + "");
            }
        });
    }

    /**
     * 将PCM格式的文件写入WAV
     */
    private void convertPcm2Wav() {
        //Pcm的文件路劲
        String pcmPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hdl_audio_cache/"
                + mCurrentName +".pcm";
        //输出的wav文件路径
        String wavPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/hdl_audio_cache/"
                + mCurrentName + ".wav";
        //把pcm转成wav
        AudioUtil.convertPcm2Wav(pcmPath, wavPath, 16000, 1, 16);
        Log.e(TAG, "转换完成");
    }

    /**
     * 流完全写入并且关闭
     */
    private void flushAndClose() {
        try {
            mFos.flush();
            mFos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        Log.e(TAG, "流刷新和关闭完成");
    }

    /**
     * 将合成的数据写入文件中
     *
     * @param data
     */
    private void saveDataToFile(byte[] data) {
        try {
            mFos.write(data);
        } catch (Exception e) {

        }
    }

    @Override
    public void onDestroy() {
        // 最终，释放客户端
        client.release();
        super.onDestroy();
    }

}
